{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Introduction to Interact.jl"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div id=\"interact-js-shim\">\n",
       "    <script charset=\"utf-8\">\n",
       "(function (IPython, $, _, MathJax) {\n",
       "    $.event.special.destroyed = {\n",
       "\tremove: function(o) {\n",
       "\t    if (o.handler) {\n",
       "\t\to.handler.apply(this, arguments)\n",
       "\t    }\n",
       "\t}\n",
       "    }\n",
       "\n",
       "    var OutputArea = IPython.version >= \"4.0.0\" ? require(\"notebook/js/outputarea\").OutputArea : IPython.OutputArea;\n",
       "\n",
       "    var redrawValue = function (container, type, val) {\n",
       "\tvar selector = $(\"<div/>\");\n",
       "\tvar oa = new OutputArea(_.extend(selector, {\n",
       "\t    selector: selector,\n",
       "\t    prompt_area: true,\n",
       "\t    events: IPython.events,\n",
       "\t    keyboard_manager: IPython.keyboard_manager\n",
       "\t})); // Hack to work with IPython 2.1.0\n",
       "\n",
       "\tswitch (type) {\n",
       "\tcase \"image/png\":\n",
       "            var _src = 'data:' + type + ';base64,' + val;\n",
       "\t    $(container).find(\"img\").attr('src', _src);\n",
       "\t    break;\n",
       "\tdefault:\n",
       "\t    var toinsert = OutputArea.append_map[type].apply(\n",
       "\t\toa, [val, {}, selector]\n",
       "\t    );\n",
       "\t    $(container).empty().append(toinsert.contents());\n",
       "\t    selector.remove();\n",
       "\t}\n",
       "\tif (type === \"text/latex\" && MathJax) {\n",
       "\t    MathJax.Hub.Queue([\"Typeset\", MathJax.Hub, toinsert.get(0)]);\n",
       "\t}\n",
       "    }\n",
       "\n",
       "\n",
       "    $(document).ready(function() {\n",
       "\tfunction initComm(evt, data) {\n",
       "\t    var comm_manager = data.kernel.comm_manager;\n",
       "        //_.extend(comm_manager.targets, require(\"widgets/js/widget\"))\n",
       "\t    comm_manager.register_target(\"Signal\", function (comm) {\n",
       "            comm.on_msg(function (msg) {\n",
       "                var val = msg.content.data.value;\n",
       "                $(\".signal-\" + comm.comm_id).each(function() {\n",
       "                var type = $(this).data(\"type\");\n",
       "                if (typeof(val[type]) !== \"undefined\" && val[type] !== null) {\n",
       "                    redrawValue(this, type, val[type], type);\n",
       "                }\n",
       "                });\n",
       "                delete val;\n",
       "                delete msg.content.data.value;\n",
       "            });\n",
       "\t    });\n",
       "\n",
       "\t    // coordingate with Comm and redraw Signals\n",
       "\t    // XXX: Test using Reactive here to improve performance\n",
       "\t    $([IPython.events]).on(\n",
       "\t\t'output_appended.OutputArea', function (event, type, value, md, toinsert) {\n",
       "\t\t    if (md && md.reactive) {\n",
       "                // console.log(md.comm_id);\n",
       "                toinsert.addClass(\"signal-\" + md.comm_id);\n",
       "                toinsert.data(\"type\", type);\n",
       "                // Signal back indicating the mimetype required\n",
       "                var comm_manager = IPython.notebook.kernel.comm_manager;\n",
       "                var comm = comm_manager.comms[md.comm_id];\n",
       "                comm.then(function (c) {\n",
       "                    c.send({action: \"subscribe_mime\",\n",
       "                       mime: type});\n",
       "                    toinsert.bind(\"destroyed\", function() {\n",
       "                        c.send({action: \"unsubscribe_mime\",\n",
       "                               mime: type});\n",
       "                    });\n",
       "                })\n",
       "\t\t    }\n",
       "\t    });\n",
       "\t}\n",
       "\n",
       "\ttry {\n",
       "\t    // try to initialize right away. otherwise, wait on the status_started event.\n",
       "\t    initComm(undefined, IPython.notebook);\n",
       "\t} catch (e) {\n",
       "\t    $([IPython.events]).on('kernel_created.Kernel kernel_created.Session', initComm);\n",
       "\t}\n",
       "    });\n",
       "})(IPython, jQuery, _, MathJax);\n",
       "</script>\n",
       "    <script>\n",
       "        window.interactLoadedFlag = true\n",
       "       $(\"#interact-js-shim\").bind(\"destroyed\", function () {\n",
       "           if (window.interactLoadedFlag) {\n",
       "               console.warn(\"JavaScript required by Interact will be removed if you remove this cell or run using Interact more than once.\")\n",
       "           }\n",
       "       })\n",
       "       $([IPython.events]).on(\"kernel_starting.Kernel kernel_restarting.Kernel\", function () { window.interactLoadedFlag = false })\n",
       "   </script>\n",
       "</div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "using Reactive, Interact"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Interact.jl provides interactive widgets for IJulia. Interaction relies on [Reactive.jl](http://julialang.org/Reactive.jl/) reactive programming package. Reactive provides the type `Signal` which represent time-varying values. For example, a Slider widget can be turned into a \"signal of numbers\". Execute the following two cells, and then move the slider. You will see that the value of `signal(slider)` changes accordingly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.5, nactions=1),\"Slider X:\",0.5,0.0:0.1:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = slider(0:.1:1,label=\"Slider X:\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.5"
      ]
     },
     "execution_count": 3,
     "metadata": {
      "comm_id": "4fa54d12-c98a-499d-9a70-9d92bb50c7ea",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "signal(s)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let us now inspect the types of these entities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Interact.Slider{Float64}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "display(typeof(s));\n",
    "isa(s, Widget)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Reactive.Signal{Float64}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "true"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "display(typeof(signal(s)));\n",
    "isa(signal(s), Signal{Float64})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can have many instances of the same widget in a notebook, and they stay in sync:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.5, nactions=2),\"Slider X:\",0.5,0.0:0.1:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Using Widget Signals"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A slider is useless if you cannot do more with it than just watch its value. Thankfully we can transform one signal into another, which means we can transform the signal of values that the slider takes into, say a signal of it's squares:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.25"
      ]
     },
     "execution_count": 7,
     "metadata": {
      "comm_id": "c838fd1f-95d2-458e-9258-80eea0419c88",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "xsquared = map(x -> x*x, signal(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Go ahead and vary the slider to see this in action."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can transform a signal into pretty much anything else. Let's use the Color package to produce different saturations of red:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version\"1.0\" encoding=\"UTF-8\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"\n",
       "     width=\"25mm\" height=\"25mm\" viewBox=\"0 0 1 1\">\n",
       "     <rect width=\"1\" height=\"1\"\n",
       "           fill=\"#808080\" stroke=\"none\"/>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "RGB{Float64}(0.5,0.5,0.5)"
      ]
     },
     "execution_count": 8,
     "metadata": {
      "comm_id": "d8a3af5c-815a-4cf1-8787-61b7355bfd40",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using Colors\n",
    "map(x -> RGB(x, 0.5, 0.5), signal(s))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can of course use several inputs as arguments to `map` enabling you to combine many signals. Let's create a full color-picker."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.5, nactions=1),\"R\",0.5,0.0:0.01:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.5, nactions=1),\"G\",0.5,0.0:0.01:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.5, nactions=1),\"B\",0.5,0.0:0.01:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "r = slider(0:0.01:1, label=\"R\")\n",
    "g = slider(0:0.01:1, label=\"G\")\n",
    "b = slider(0:0.01:1, label=\"B\")\n",
    "map(display, [r,g,b]);"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/svg+xml": [
       "<?xml version\"1.0\" encoding=\"UTF-8\"?>\n",
       "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n",
       " \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n",
       "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"\n",
       "     width=\"25mm\" height=\"25mm\" viewBox=\"0 0 1 1\">\n",
       "     <rect width=\"1\" height=\"1\"\n",
       "           fill=\"#808080\" stroke=\"none\"/>\n",
       "</svg>\n"
      ],
      "text/plain": [
       "RGB{Float64}(0.5,0.5,0.5)"
      ]
     },
     "execution_count": 10,
     "metadata": {
      "comm_id": "7915f3b9-1865-4266-a62e-2d452e702476",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "color = map((x, y, z) -> RGB(x, y, z), signal(r), signal(g), signal(b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can use the HTML widget to write some text you can change the color of."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style='color:#808080'>Hello, World!</div>"
      ],
      "text/plain": [
       "HTML{String}(\"<div style='color:#808080'>Hello, World!</div>\")"
      ]
     },
     "execution_count": 11,
     "metadata": {
      "comm_id": "bb55b6b3-81f2-4a0f-8832-8b4fc28d840e",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(color -> HTML(string(\"<div style='color:#\", hex(color), \"'>Hello, World!</div>\")), signal(color))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## The @manipulate Macro"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `@manipulate` macro lets you play with any expression using widgets. We could have, for example, used `@manipulate` to make a color picker along with our HTML output in one line of code:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Options{:SelectionSlider,Float64}(Signal{Float64}(0.5, nactions=1),\"r\",0.5,\"0.5\",Interact.OptionDict(DataStructures.OrderedDict(\"0.0\"=>0.0,\"0.05\"=>0.05,\"0.1\"=>0.1,\"0.15\"=>0.15,\"0.2\"=>0.2,\"0.25\"=>0.25,\"0.3\"=>0.3,\"0.35\"=>0.35,\"0.4\"=>0.4,\"0.45\"=>0.45…),Dict(1.0=>\"1.0\",0.95=>\"0.95\",0.3=>\"0.3\",0.45=>\"0.45\",0.25=>\"0.25\",0.35=>\"0.35\",0.7=>\"0.7\",0.0=>\"0.0\",0.85=>\"0.85\",0.15=>\"0.15\"…)),Any[],Any[],true,\"horizontal\")"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Options{:SelectionSlider,Float64}(Signal{Float64}(0.5, nactions=1),\"g\",0.5,\"0.5\",Interact.OptionDict(DataStructures.OrderedDict(\"0.0\"=>0.0,\"0.05\"=>0.05,\"0.1\"=>0.1,\"0.15\"=>0.15,\"0.2\"=>0.2,\"0.25\"=>0.25,\"0.3\"=>0.3,\"0.35\"=>0.35,\"0.4\"=>0.4,\"0.45\"=>0.45…),Dict(1.0=>\"1.0\",0.95=>\"0.95\",0.3=>\"0.3\",0.45=>\"0.45\",0.25=>\"0.25\",0.35=>\"0.35\",0.7=>\"0.7\",0.0=>\"0.0\",0.85=>\"0.85\",0.15=>\"0.15\"…)),Any[],Any[],true,\"horizontal\")"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Options{:SelectionSlider,Float64}(Signal{Float64}(0.5, nactions=1),\"b\",0.5,\"0.5\",Interact.OptionDict(DataStructures.OrderedDict(\"0.0\"=>0.0,\"0.05\"=>0.05,\"0.1\"=>0.1,\"0.15\"=>0.15,\"0.2\"=>0.2,\"0.25\"=>0.25,\"0.3\"=>0.3,\"0.35\"=>0.35,\"0.4\"=>0.4,\"0.45\"=>0.45…),Dict(1.0=>\"1.0\",0.95=>\"0.95\",0.3=>\"0.3\",0.45=>\"0.45\",0.25=>\"0.25\",0.35=>\"0.35\",0.7=>\"0.7\",0.0=>\"0.0\",0.85=>\"0.85\",0.15=>\"0.15\"…)),Any[],Any[],true,\"horizontal\")"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div style='color:#808080'>Color me</div>"
      ],
      "text/plain": [
       "HTML{String}(\"<div style='color:#808080'>Color me</div>\")"
      ]
     },
     "execution_count": 12,
     "metadata": {
      "comm_id": "4b60fa0a-3a28-463b-86d6-d483758a81f9",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "@manipulate for r = 0:.05:1, g = 0:.05:1, b = 0:.05:1\n",
    "    HTML(string(\"<div style='color:#\", hex(RGB(r,g,b)), \"'>Color me</div>\"))\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Signal of Widgets"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can in fact create signal of other widgets to update them reactively. We have seen one case with `HTML` above. Let us now create a signal of Sliders:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(3.1, nactions=3),\"x\",3.1,0.0:0.1:6.2,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(-0.0830894028174964, nactions=1),\"sin(2x)\",-0.0830894028174964,-1.0:0.05:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.9965420970232175, nactions=1),\"cos(2x)\",0.9965420970232175,-1.0:0.05:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = slider(0:.1:2pi, label=\"x\")\n",
    "s = map(a -> slider(-1:.05:1, value=sin(2a), label=\"sin(2x)\"), signal(x))\n",
    "c = map(a -> slider(-1:.05:1, value=cos(2a), label=\"cos(2x)\"), signal(x))\n",
    "map(display, [x,s,c]);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now vary the x slider to see sin(2x) and cos(2x) get set to their appropriate values."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But in the above case, you cannot also use sin(2x) and cos(2x) sliders as input values (without doing tricky stuff beyond the scope of this introduction). To do this more simply, we will create a separate Input signal and pass it as an argument to map, to be the signal that the widget updates. Example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.0"
      ]
     },
     "execution_count": 14,
     "metadata": {
      "comm_id": "6c036a05-15cd-4351-9574-3a2240ade2ad",
      "reactive": true
     },
     "output_type": "execute_result"
    }
   ],
   "source": [
    "fx = Signal(0.0) # A float input"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(3.1, nactions=2),\"x\",3.1,0.0:0.1:6.2,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [],
      "text/plain": [
       "Interact.Slider{Float64}(Signal{Float64}(0.04158066243329049, nactions=2),\"f(x)\",0.04158066243329049,-1.0:0.05:1.0,\"horizontal\",true,\".3f\",true)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "0.04158066243329049"
      ]
     },
     "metadata": {
      "comm_id": "6c036a05-15cd-4351-9574-3a2240ade2ad",
      "reactive": true
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "x = slider(0:.1:2pi, label=\"x\")\n",
    "y = map(v -> slider(-1:.05:1, value=sin(v), signal=fx, label=\"f(x)\"), signal(x))\n",
    "map(display, (x,y,fx));"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "f(x) will update as x changes. But if the user slides f(x) then the `fx` signal takes the value chosen by the user."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 0.5.0",
   "language": "julia",
   "name": "julia-0.5"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "0.5.0"
  },
  "widgets": {
   "state": {
    "077b09eb-b5a1-4e1b-899e-a7245ef0ad31": {
     "views": [
      {
       "cell_index": 26
      }
     ]
    },
    "0db3500a-3b54-4b1d-a1e4-be5730770f3e": {
     "views": [
      {
       "cell_index": 23
      }
     ]
    },
    "117c3c58-3627-495b-868a-6f4d9ffb98c2": {
     "views": [
      {
       "cell_index": 17
      }
     ]
    },
    "1fdf6629-5e59-4595-9907-67d646324225": {
     "views": [
      {
       "cell_index": 30
      }
     ]
    },
    "39194171-094d-4433-b609-f9cd848c0b08": {
     "views": [
      {
       "cell_index": 17
      }
     ]
    },
    "3d099a9b-7f4a-4c8a-b6ca-97288c325491": {
     "views": [
      {
       "cell_index": 30
      }
     ]
    },
    "470bfd15-5fe3-4930-8980-2b5981b3a17b": {
     "views": [
      {
       "cell_index": 30
      }
     ]
    },
    "4d25980e-3c2a-4fb5-8a9f-2a6cdce721d3": {
     "views": [
      {
       "cell_index": 26
      }
     ]
    },
    "62f947ae-8c11-4950-9948-36c8dcb97d53": {
     "views": [
      {
       "cell_index": 26
      }
     ]
    },
    "796508de-26be-43b0-b5d0-3301708e49e3": {
     "views": [
      {
       "cell_index": 30
      }
     ]
    },
    "9554341f-f900-454e-930a-54fd8d4efba7": {
     "views": [
      {
       "cell_index": 30
      }
     ]
    },
    "9f429f55-d1aa-423d-825e-d0473a8c3284": {
     "views": [
      {
       "cell_index": 26
      }
     ]
    },
    "a0dcb116-4f3e-479a-ad32-c0cdf845c7c3": {
     "views": [
      {
       "cell_index": 23
      }
     ]
    },
    "bb79b6e9-3f51-4bb5-a26a-34faaf217423": {
     "views": [
      {
       "cell_index": 17
      }
     ]
    },
    "c6190b96-107a-4dcf-8f65-4f07d4513922": {
     "views": [
      {
       "cell_index": 23
      }
     ]
    },
    "cc4ffe70-0e6f-4d6a-acd7-0748e6f650c4": {
     "views": [
      {
       "cell_index": 23
      }
     ]
    },
    "cde153a3-7066-4225-85be-082315c47118": {
     "views": [
      {
       "cell_index": 23
      }
     ]
    },
    "cf5562f2-eaf0-43b4-a64f-5ac232c117a5": {
     "views": [
      {
       "cell_index": 17
      }
     ]
    },
    "d0f5f1bf-2780-400b-a656-5acdd6158d14": {
     "views": [
      {
       "cell_index": 17
      }
     ]
    },
    "d359741d-7785-424f-a09e-7241922d84b7": {
     "views": [
      {
       "cell_index": 26
      }
     ]
    },
    "dc6509c0-d93e-402a-bf05-6ca64a3c6574": {
     "views": [
      {
       "cell_index": 17
      }
     ]
    },
    "f198e321-d200-4d30-a610-bb5f84020f2a": {
     "views": [
      {
       "cell_index": 3
      },
      {
       "cell_index": 9
      }
     ]
    },
    "f491e3a0-0ffb-4d7a-b2c5-348759a5bbbc": {
     "views": [
      {
       "cell_index": 23
      }
     ]
    }
   },
   "version": "1.2.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
